Architecture et configuration de l’application
1) Les trois niveaux d’app Flutter
Flutter propose trois niveaux principaux :
- WidgetsApp (niveau bas, minimal)
- MaterialApp (design Material)
- CupertinoApp (design iOS)
WidgetsApp (bas niveau)
WidgetsApp fournit la gestion de base (routing, focus, localisation), mais aucun style par défaut.
import 'package:flutter/widgets.dart';
void main() {
runApp(const MinimalApp());
}
class MinimalApp extends StatelessWidget {
const MinimalApp({super.key});
Widget build(BuildContext context) {
return WidgetsApp(
color: const Color(0xFF2196F3),
builder: (context, child) {
return const Directionality(
textDirection: TextDirection.ltr,
child: Center(child: Text('App minimale (WidgetsApp)')),
);
},
);
}
}
N'utiliser une WidgetsApp seulement si vous voulez tout contrôler vous‑même.
Contrôles disponibles avec WidgetsApp
Widgets de base (sans style Material) :
- Conteneurs : Container, SizedBox, Padding, Row, Column, Stack, Expanded, Wrap
- Texte : Text, RichText, DefaultTextStyle
- Entrées : TextField, EditableText
- Listes : ListView, GridView, SingleChildScrollView
- Navigation : Navigator, Route
- Gestion d'état : StatefulWidget, StatelessWidget, InheritedWidget
- Images : Image, AssetImage, NetworkImage
- Gestes : GestureDetector, InkWell
- Boîtes de dialogue : showDialog, AlertDialog (non-stylisé)
- Média : Video, Audio (via plugins)
Tous les contrôles sont "bruts" sans design prédéfini. Vous devez styliser manuellement avec Container, TextStyle, etc.
MaterialApp (Android / Design Material)
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Accueil')),
body: Center(
child: ElevatedButton(
onPressed: () {},
child: const Text('Bouton Material'),
),
),
);
}
}
Contrôles disponibles avec MaterialApp
Widgets Material Design :
- Layout : Scaffold, AppBar, FloatingActionButton, BottomAppBar, BottomNavigationBar, BottomSheet, Drawer, TabBar, TabBarView
- Boutons : ElevatedButton, TextButton, OutlinedButton, IconButton, FloatingActionButton, PopupMenuButton
- Entrées : TextField, TextFormField, Checkbox, Radio, Switch, Slider, DatePicker, TimePicker
- Listes : ListView, GridView, ListTile, Card, ExpansionTile, DataTable
- Boîtes de dialogue : AlertDialog, SimpleDialog, SnackBar, showDialog, showModalBottomSheet
- Indicateurs : CircularProgressIndicator, LinearProgressIndicator, Tooltip
- Cartes : Card
- Pages : PageView, Stepper, WillPopScope
- Thème : ThemeData, colorScheme, TextTheme, AppBarTheme
Tous les contrôles sont stylisés automatiquement selon le theme et le colorScheme configurés.
CupertinoApp (iOS / Design Apple)
import 'package:flutter/cupertino.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return const CupertinoApp(
title: 'Cupertino App',
home: CupertinoHomeScreen(),
);
}
}
class CupertinoHomeScreen extends StatelessWidget {
const CupertinoHomeScreen({super.key});
Widget build(BuildContext context) {
return const CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Accueil'),
),
child: Center(
child: Text('Bouton iOS'),
),
);
}
}
Contrôles disponibles avec CupertinoApp
Widgets Cupertino (iOS Design) :
- Layout : CupertinoPageScaffold, CupertinoTabScaffold, CupertinoSliverNavigationBar
- Navigation : CupertinoNavigationBar, CupertinoTabBar, CupertinoSliverRefreshControl
- Boutons : CupertinoButton, CupertinoButton.filled
- Entrées : CupertinoTextField, CupertinoSlider, CupertinoSwitch, CupertinoSegmentedControl
- Sélecteurs : CupertinoPicker, CupertinoDatePicker, CupertinoTimerPicker
- Boîtes de dialogue : CupertinoAlertDialog, CupertinoActionSheetAction, showCupertinoDialog
- Listes : CupertinoListTile, CupertinoListSection
- Indicateurs : CupertinoActivityIndicator
- Curseur : CupertinoScrollbar
- Thème : CupertinoThemeData (simplifié comparé à Material)
Tous les contrôles respectent le style iOS (pas de Material Design).
2) Architecture adaptive (Material + Cupertino)
Si vous voulez une expérience Android et iOS différente, vous pouvez détecter la plateforme et retourner un MaterialApp ou un CupertinoApp.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
final isCupertino = defaultTargetPlatform == TargetPlatform.iOS;
if (isCupertino) {
return const CupertinoApp(
title: 'App iOS',
home: AdaptiveHomeScreen(),
);
}
return MaterialApp(
title: 'App Android',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
home: const AdaptiveHomeScreen(),
);
}
}
class AdaptiveHomeScreen extends StatelessWidget {
const AdaptiveHomeScreen({super.key});
Widget build(BuildContext context) {
final isCupertino = defaultTargetPlatform == TargetPlatform.iOS;
if (isCupertino) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('Accueil iOS'),
),
child: Center(
child: CupertinoButton.filled(
onPressed: () {},
child: const Text('Bouton iOS'),
),
),
);
}
return Scaffold(
appBar: AppBar(title: const Text('Accueil Android')),
body: Center(
child: ElevatedButton(
onPressed: () {},
child: const Text('Bouton Material'),
),
),
);
}
}
3) Quand choisir quoi ?
| Cas | Option recommandée |
|---|---|
| App multiplateforme simple | MaterialApp |
| App iOS natif | CupertinoApp |
| UI 100% custom | WidgetsApp |
| App adaptative Android/iOS | MaterialApp + CupertinoApp conditionnel |
4) Bonnes pratiques
- Séparer la logique et l’UI pour faciliter l’adaptation
- Réutiliser le même modèle de données (même si l’UI change)
- Centraliser la navigation pour éviter les incohérences
- Adapter uniquement le rendu, pas toute l’app
- Tester sur les différentes plateformes